package com.tidc.manage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tidc.manage.constant.DatabaseField;
import com.tidc.manage.constant.RedisPrefixField;
import com.tidc.manage.dto.UserTokenDTO;
import com.tidc.manage.domain.User;
import com.tidc.manage.exception.AuthenticationFailureException;
import com.tidc.manage.mapper.UserMapper;
import com.tidc.manage.service.IUserRoleService;
import com.tidc.manage.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.javassist.NotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 张朝锋
 * @since 2018-09-14
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    /**
     * 认证服务器地址
     */
    @Value("${ResourceServerConfiguration.oauthUrl}")
    private String oauthUrl;

    /**
     * 认证服务器认证接口
     */
    @Value("${ResourceServerConfiguration.oauthTokenUrl}")
    private String oauthTokenUrl;
    /**
     * 认证服务器登出接口
     */
    @Value("${ResourceServerConfiguration.logoutUrl}")
    private String logoutUrl;

    /**
     * 客户端账户Id
     */
    @Value("${ResourceServerConfiguration.clientId}")
    private String clientId;

    /**
     * 客户端秘文
     */
    @Value("${ResourceServerConfiguration.clientSecret}")
    private String clientSecret;

    /**
     * redis 模板
     */
    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    @Autowired
    private IUserRoleService userRoleService;

    /**
     * spring对web请求的封装类 (所以说，约定大于配置!)
     */
    private RestTemplate restTemplate = new RestTemplate();

    /**
     * 登录远程验证
     *
     * @param user 封装用户信息的对象，包括了用户名和密码
     * @return 用户令牌
     */
    @Override
    public UserTokenDTO login(User user) throws AuthenticationFailureException {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "password");
        params.add("username", user.getId());
        params.add("password", user.getPassword());
        params.add("scope", "all");
        params.add("client_id", clientId);
        params.add("client_secret", clientSecret);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
        UserTokenDTO userTokenDTO;
        try {
            userTokenDTO = restTemplate.postForObject(oauthTokenUrl, requestEntity, UserTokenDTO.class);
        } catch (RestClientException rce) {
            rce.printStackTrace();
            throw new AuthenticationFailureException();
        }
        //将token存入redis
        Assert.notNull(userTokenDTO, "userTokenDTO is null!");
        redisTemplate.opsForValue().set(RedisPrefixField.USER_TOKEN_DTO + user.getId(), userTokenDTO, userTokenDTO.getExpires_in(), TimeUnit.SECONDS);
        user.setPassword(null);
        return userTokenDTO;
    }

    @Override
    public Integer logout(String userId, String accessToken) {
        restTemplate.getForObject(logoutUrl + "?token=" + accessToken, Object.class);
        redisTemplate.delete(RedisPrefixField.USER_TOKEN_DTO + userId);
        return 1;
    }

    @Override
    public boolean hasUser(String userId) {
        return baseMapper.selectCount(
                new QueryWrapper<User>()
                        .eq(DatabaseField.USER_ID, userId)) != 0;
    }

    @Override
    public Integer updateUserOfStudentForPasswordByStudentId(String studentId, User user, String accessToken) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("password", user.getPassword());
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);

        restTemplate.put(
                oauthUrl + "/alter/password/{userId}?access_token={access_token}",
                requestEntity, studentId, accessToken);
        //强制用户登出
        logout(studentId, accessToken);
        return 1;
    }

    @Override
    public void deleteUserById(String id) throws NotFoundException {
        if (baseMapper.selectById(id) == null) {
            throw new NotFoundException("User(" + id + ")");
        }
        // 不要忘了这个傻批的权限，不然就变成孤儿数据了
        userRoleService.deleteUserRoleByUserId(id);
        baseMapper.deleteById(id);
    }
}
